OC 和 Swift 自定义打印输出

iOS 开发过程中,经常需要在 Debug 模式下使用打印日志输出(在 OC 中默认是使用 NSLog 打印, Swift 中默认使用 print 打印)进行调试,但是 Release 之后打包生成安装文件之后就不需要这些输出了,并且 Release 之后打印输出还会影响 App 的性能,苹果上架审核规则也是不允许的,下面就分别介绍 OC 和 Swift 下怎么实现 Debug 模式下打印输出,Release 模式之后不打印输出

OC 自定义 NSLog 输出

在 OC 中可以使用如下宏定义,把下面的代码加入到工程的 PCH 文件中即可:

1
2
3
4
5
#ifdef DEBUG
#define NSLog(format, ...) NSLog(format, ## __VA_ARGS__)
#else
#define NSLog(format, ...)
#endif

上面这段代码的意思就是用宏指令做一个判断,如果 DEBUG 为真,则编译#ifdef到#endif宏定义,否则编译器就不编译,然后就可以在项目里继续使用 NSLog 打印日志输出了,不用担心 Release 下还会打印日志输出了

既然可以自己定义 NSLog 那为什么不让打印的信息更佳丰富一些呢,比如加入打印的文件名、函数名、打印位置的行数呢,然后可以修改一下上面的代码:

1
2
3
4
5
#if DEBUG
#define NSLog(FORMAT, ...) NSLog(@"File:%s Function:%s Line:%d Content:%@\n", __FILE__,__FUNCTION__, __LINE__, [NSString stringWithFormat:FORMAT, ##__VA_ARGS__])
#else
#define NSLog(FORMAT, ...)
#endif

使用上面的宏定义就可以得到了下面的打印的结果如下:

1
2017-05-12 23:54:25.888 NSLogDemo[15672:715649] File:/Users/xiaovv/Documents/DemoCode/NSLogDemo/NSLogDemo/ViewController.m Function:-[ViewController viewDidLoad] Line:20 Content:NSLogDemo

下面介绍一下宏定义里面几个参数:

  • __VA_ARGS__ 是一个可变参数的宏,这个可变参数的宏是新的C99规范中新增的,目前似乎只有gcc支持(VC6.0的编译器不支持),宏前面加上##的作用在于,当可变参数的个数为0时,这里的##起到把前面多余的”,”去掉的作用,否则会编译出错
  • __FILE__ 宏在预编译时会替换成当前的源文件名
  • __LINE__宏在预编译时会替换成当前的行号
  • __FUNCTION__宏在预编译时会替换成当前的函数名称

补充1 Xcode 8 如何添加 PCH 文件:

1. 打开你的 Xcode 工程. 在Supporting Files目录下,使用 Command + N 新建一个文件选择 other 下面的 PCH FilePCH 文件名格式建议为 工程名-Prefix.pch,比如:NSLogDemo-Prefix.pch

2. 在工程的 Build Settings 里搜索找到 Prefix Header 选项,然后给这个选项配置路径为:项目名称/PCH 文件名,比如:NSLogDemo/NSLogDemo-Prefix.pch

3. 将 Precompile Prefix HeaderYES,预编译后的 PCH 文件会被缓存起来,可以提高编译速度

4. Clean 一下工程,就可以使用 PCH 文件了

Swift 自定义 Print 输出

Swift 中已经没有宏定义文件了,但是 Swift 只要在一个文件中声明了一个公开的方法, 其他文件都是可以访问到的. 所以可以把自定义 Log 的方法放到一个公共使用的方法的文件中,可以这样定义:

1
2
3
4
5
6
7
8
9
10
11
12
import UIKit
func XWLog<T>(_ messsage : T, file : String = #file, funcName : String = #function, lineNum : Int = #line{
#if DEBUG
let fileName = (file as NSString).lastPathComponent
print("File:\(fileName) Function:\(funcName) Line:\(lineNum) Content:\(messsage)")
#endif
}

使用上面的 XWLog 打印的结果如下:

1
File:ViewController.swift Function:viewDidLoad() Line:18 Content:LogDemo

这里 #if DEBUG 以及 #endif 还是宏,但是这个宏和 OC 中的宏是两回事了,因为这个是我们自定义的宏,Swift2 需要我们自己去配置这个自定义的宏,Swift 3 貌似默认已经配置了,Swift 2 需要在 Building Settings 进行如下设置

解释一下 XWLog 函数:

  • 使用泛型函数( 标志),可以让调用者传递任意的类型,进行打印Log的操作,可以自行搜索 Swift 泛型函数相关内容
  • #file,#function,#line 是编译器几个很有用的编译符号
符号 类型 描述
#file String 包含这个符号的文件的路径
#line Int 符号出现处的行号
#column Int 符号出现处的列
#function String 包含这个符号的方法名字

以上

本人刚开始写博客,主要是为了给自己的知识点做一个笔记,方便自己以后查阅,如果能让别人有所启发也是荣幸之至!如有错误,欢迎指正!